package me.zhengjie.modules.web.service.chat.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.Data;
import me.zhengjie.config.entity.PageData;
import me.zhengjie.config.exception.WeChatException;
import me.zhengjie.constant.ConstantUtils;
import me.zhengjie.modules.system.domain.*;
import me.zhengjie.modules.system.service.WxUserService;
import me.zhengjie.modules.system.service.mapstruct.UserChatPlusMapper;
import me.zhengjie.modules.utils.ChatUtils;
import me.zhengjie.modules.web.domain.chat.*;
import me.zhengjie.modules.web.service.chat.IBaiduChatService;
import me.zhengjie.modules.web.service.chat.validate.IReplayFeeValidate;
import me.zhengjie.modules.web.service.mybatisplus.*;
import me.zhengjie.request.ATMRContext;
import me.zhengjie.utils.DateUtil;
import me.zhengjie.utils.StringUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BaiduChatServiceImpl implements IBaiduChatService {

    @Autowired
    private IUserChatPlusService chatPlusService;
    @Autowired
    private UserChatPlusMapper chatPlusMapper;
    @Autowired
    private IUserChatRecordPlusService chatRecordPlusService;

    @Autowired
    private WxUserService wxUserService;

    @Autowired
    List<IReplayFeeValidate> replayFeeValidateList;

    @Autowired
    private IUserChatPriceSettingPlusService settingPlusService;

    @Autowired
    private IUserChatKeyReplacePlusService replacePlusService;

    @Autowired
    private IUserChatKeyMappingPlusService mappingPlusService;

    @Autowired
    private IUserChatQuickReplyPlusService quickReplyPlusService;

    private static final Logger log = LoggerFactory.getLogger(BaiduChatServiceImpl.class);

    @Override
    public BaiduChatResponse replay(BaiduChatRequest request) {
        String openId = ATMRContext.getContext().getOpenId();
        String question = request.getQuestion();
        if (StringUtils.isAnyBlank(question, openId)) {
            throw new WeChatException("缺少参数");
        }
        String origQuestion = question;
        long startTime = System.currentTimeMillis();
        BaiduChatResponse response = new BaiduChatResponse();
        boolean success = validate(openId, response);
        if (!success) {
            throw new WeChatException("使用次数已达上限，重新购买");
        }
        boolean needReplace = true;
        log.info("次数上限耗时：" + (System.currentTimeMillis() - startTime));
        String replay = "";
        Replay replay1 = quickReplyById(request.getQuickReplyId());
        if (Objects.isNull(replay1)) {
            List<UserChatQuickreply> list = quickReplyPlusService.list();
            replay1 = quickQuestionEqualMatchReply(list, question);
            if (Objects.isNull(replay1)) {
                replay1 = quickKeyWordLikeMatchReply(list, question);
            }
        }
        if (Objects.nonNull(replay1)) {
            replay = replay1.getReplay();
            needReplace = replay1.getNeedReplace();
        }
        if (StringUtils.isBlank(replay)) {
            question = getFinalQuestion(question);
            log.info("问题是==========================" + question);
            replay = ChatUtils.getInstance().getStreamReplay(question);
            if (StringUtils.isBlank(replay)) {
                throw new WeChatException("接口异常");
            }
        }
        log.info("文心一言调用耗时：" + (System.currentTimeMillis() - startTime));
        if (StringUtils.isBlank(replay)) {
            throw new WeChatException("服务异常,请稍后再试");
        }
        response.setAnswer(replay);
        if (needReplace) {
            //关键字替换
            List<UserChatKeyreplace> replaceList = replacePlusService.list();
            if (CollectionUtils.isNotEmpty(replaceList)) {
                for (UserChatKeyreplace s : replaceList) {
                    replay = StrUtil.replace(replay, s.getKeyword(), s.getReplaceContent());
                }
                response.setAnswer(replay);
            }
        }

        if (response.getSurplusUnit() == 1) {
            response.setSurplusTimes(response.getSurplusTimes() - 1);
        }

        LambdaQueryWrapper<UserChatRecord> recordWrapper = new LambdaQueryWrapper<>();
        recordWrapper.eq(UserChatRecord::getOpenId, openId);
        List<UserChatRecord> list = chatRecordPlusService.list(recordWrapper);
        if (CollectionUtils.isEmpty(list)) {
            UserChatRecord record = new UserChatRecord();
            WxUser wxUser = wxUserService.findByOpenId(openId);
            if (Objects.isNull(wxUser)) {
                throw new WeChatException("参数异常");
            }
            record.setOpenId(openId);
            record.setCreateTime(DateUtil.TimestampNow());
            record.setMobile(wxUser.getMobile());
            record.setNickName(wxUser.getNickname());
            record.setRealName(wxUser.getRealName());
            chatRecordPlusService.save(record);
        } else {
            UserChatRecord record = new UserChatRecord();
            record.setUpdateTime(DateUtil.TimestampNow());
            LambdaQueryWrapper<UserChatRecord> wrapper = new LambdaQueryWrapper();
            wrapper.eq(UserChatRecord::getId, list.get(0).getId());
            chatRecordPlusService.update(record, wrapper);
        }

        UserChat userChat = new UserChat();
        userChat.setQuestion(origQuestion);
        userChat.setAnswer(replay);
        userChat.setOpenId(openId);
        userChat.setCreateTime(DateUtil.TimestampNow());
        userChat.setChatStatus(ConstantUtils.Valid);
        userChat.setQuestionType(0);
        chatPlusService.save(userChat);
        return response;
    }

    /**
     * 是否可聊天
     *
     * @param openId
     * @param response
     * @return
     */
    private boolean validate(String openId, BaiduChatResponse response) {
        for (IReplayFeeValidate validate : replayFeeValidateList) {
            boolean success = validate.validate(openId, response);
            if (success) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void getSurplusTimes(String openId, BaiduChatResponse response) {
        for (IReplayFeeValidate validate : replayFeeValidateList) {
            boolean success = validate.get(openId, response);
            if (success) {
                return;
            }
        }
    }

    @Override
    public PageData<BaiduChatHistoryResponse> history(BaiduChatHistoryRequest request) {
        String openId = ATMRContext.getContext().getOpenId();
        Page<UserChat> studentPage = Page.of(request.getPage(), request.getSize());
        LambdaQueryWrapper<UserChat> configWrapper = new LambdaQueryWrapper<>();
        configWrapper.eq(UserChat::getOpenId, openId);
        configWrapper.eq(UserChat::getChatStatus, ConstantUtils.Valid);
        configWrapper.orderByDesc(UserChat::getCreateTime);
        Page<UserChat> configPage = chatPlusMapper.selectPage(studentPage, configWrapper);
        if (Objects.isNull(configPage) || CollectionUtils.isEmpty(configPage.getRecords())) {
            return PageData.valueOf(new ArrayList<>(), 0L, 0L);
        }
        List<BaiduChatHistoryResponse> list = new ArrayList<>();
        List<UserChat> records = configPage.getRecords();
        for (UserChat s : records) {
            BaiduChatHistoryResponse resp = new BaiduChatHistoryResponse();
            resp.setId(s.getId());
            resp.setAnswer(s.getAnswer());
            resp.setQuestion(s.getQuestion());
            resp.setCreateTime(DateUtil.getTimeStamp(s.getCreateTime()));
            resp.setQuestionType(s.getQuestionType());
            list.add(resp);
        }
        list = list.stream().sorted(Comparator.comparing(BaiduChatHistoryResponse::getId)).collect(Collectors.toList());
        return PageData.valueOf(list, configPage.getTotal(), configPage.getPages());
    }

    @Override
    public List<BaiduChatPaidListResponse> getPaidList() {

        LambdaQueryWrapper<UserChatPriceSetting> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserChatPriceSetting::getSettingStatus, ConstantUtils.Valid);
        List<UserChatPriceSetting> list = settingPlusService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<BaiduChatPaidListResponse> finalList = new ArrayList<>();
        list.forEach(s -> {
            String settingKey = s.getSettingKey();
            String name = "";
            if ("Month_1".equals(settingKey)) {
                name = "30天会员";
            }
            /*else if ("Month_3".equals(settingKey)) {
                name = "3个月会员";
            } */
            else if ("Month_6".equals(settingKey)) {
                name = "半年会员";
            } else if ("Month_12".equals(settingKey)) {
                name = "一年会员";
            } else {
                return;
            }
            BaiduChatPaidListResponse resp = new BaiduChatPaidListResponse();
            resp.setChatKey(settingKey);
            resp.setPrice(new BigDecimal(s.getSettingValue()));
            resp.setName(name);
            finalList.add(resp);
        });
        return finalList.stream().sorted(Comparator.comparing(BaiduChatPaidListResponse::getPrice, Comparator.reverseOrder())).collect(Collectors.toList());
    }

    @Override
    public List<BaiduChatQuickReplyResponse> getQuickReplyList() {
        LambdaQueryWrapper<UserChatQuickreply> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserChatQuickreply::getShowIndex, ConstantUtils.Valid);
        List<UserChatQuickreply> list = quickReplyPlusService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<BaiduChatQuickReplyResponse> respList = new ArrayList<>();
        list.forEach(s -> {
            BaiduChatQuickReplyResponse resp = new BaiduChatQuickReplyResponse();
            resp.setKeyword(s.getKeyword());
            resp.setId(s.getId());
            resp.setQuestion(s.getQuestion());
            respList.add(resp);
        });
        return respList;
    }


    private String getFinalQuestion(String question) {
        List<UserChatKeymapping> mappingList = mappingPlusService.list();
        if (CollectionUtils.isEmpty(mappingList)) {
            return question;
        }
        int index = 0;
        Map<String, String> mappingMap = new HashMap<>();
        for (UserChatKeymapping userChatKeymapping : mappingList) {
            if (!question.trim().toLowerCase().contains(userChatKeymapping.getAtmrType().toLowerCase())) {
                continue;
            }
            question = question.toLowerCase().replaceAll(userChatKeymapping.getAtmrType().toLowerCase(), "replace_" + index);
            mappingMap.put("replace_" + index, userChatKeymapping.getDescribes());
            index++;
        }
        if (MapUtils.isEmpty(mappingMap)) {
            return question;
        }
        for (Map.Entry<String, String> entry : mappingMap.entrySet()) {
            question = question.toLowerCase().replaceAll(entry.getKey().toLowerCase(), entry.getValue());
        }
        return question;
    }

    /**
     * 快捷回复关键字模糊匹配
     *
     * @param list
     * @param question
     * @return
     */
    private Replay quickKeyWordLikeMatchReply(List<UserChatQuickreply> list, String question) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        String finalQuestion1 = question;
        for (UserChatQuickreply userChatQuickreply : list) {
            if (StringUtils.isBlank(userChatQuickreply.getKeyword())) {
                continue;
            }
            List<String> keywordList = Lists.newArrayList(userChatQuickreply.getKeyword().split(","));
            if (keywordList.stream().filter(s -> StringUtils.isNotBlank(s)).anyMatch(s -> finalQuestion1.toLowerCase().contains(s.toLowerCase()))) {
                Replay replay = new Replay();
                replay.setReplay(userChatQuickreply.getReplyContent());
                replay.setNeedReplace(false);
                return replay;
            }
        }
        return null;
    }

    /**
     * 快捷回复中的问题匹配
     *
     * @param list
     * @param question
     * @return
     */
    private Replay quickQuestionEqualMatchReply(List<UserChatQuickreply> list, String question) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<UserChatQuickreply> quickreplyList = list.stream().filter(s -> StringUtils.isBlank(s.getKeyword()) && StringUtils.isNotBlank(s.getReplyContent())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(quickreplyList)) {
            return null;
        }
        String finalQuestion = question;
        UserChatQuickreply userChatQuickreply = quickreplyList.stream().filter(s -> finalQuestion.toLowerCase().trim().equals(s.getQuestion().toLowerCase().trim())).findFirst().orElse(null);
        if (Objects.isNull(userChatQuickreply)) {
            return null;
        }
        Replay replay = new Replay();
        replay.setReplay(userChatQuickreply.getReplyContent());
        replay.setNeedReplace(false);
        return replay;
    }

    /**
     * 根据主键查询快捷回去
     *
     * @param quickReplyId
     * @return
     */
    private Replay quickReplyById(Integer quickReplyId) {
        if (Objects.isNull(quickReplyId)) {
            return null;
        }
        UserChatQuickreply quickreply = quickReplyPlusService.getById(quickReplyId);
        if (Objects.isNull(quickreply) || StringUtils.isBlank(quickreply.getReplyContent())) {
            return null;
        }
        Replay replay = new Replay();
        replay.setReplay(quickreply.getReplyContent());
        replay.setNeedReplace(false);
        return replay;
    }

    @Data
    public static class Replay {
        private String replay;
        private Boolean needReplace;
    }
}